package com.atguigu.gmall.realtime.util;

import com.atguigu.gmall.realtime.common.GmallConstant;
import net.minidev.json.JSONObject;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.flink.shaded.guava30.com.google.common.base.CaseFormat;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author lzc
 * @Date 2023/7/31 14:02
 */
public class JdbcUtil {
    public static void main(String[] args) throws SQLException, ClassNotFoundException {
        //System.out.println(getMysqlConnection());
    
//        List<JSONObject> list = queryList(getMysqlConnection(), "select * from gmall2023_config.table_process", null, JSONObject.class);
//        List<TableProcess> list = queryList(getMysqlConnection(), "select * from gmall2023_config.table_process", null, TableProcess.class, true);
        List<JSONObject> list = queryList(getMysqlConnection(), "select * from gmall2023.sku_info where id=?", new Object[]{10}, JSONObject.class);
        
        for (Object obj : list) {
            System.out.println(obj);
            
        }
    }
    
    /**
     * 获取 mysql 连接
     *
     * @return 到 mysql 的链接
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    public static Connection getMysqlConnection() throws ClassNotFoundException, SQLException {
        // 1. 加载 MySQL 驱动
        Class.forName(GmallConstant.MYSQL_DRIVER);
        // 2. 使用驱动管理器获取 mysql 连接
        String url = GmallConstant.MYSQL_URL;
        return DriverManager.getConnection(url, "root", "aaaaaa");
    }
    
    /**
     * 根据参数,执行查询 sql 得到所有的数据, 封装到 T 类型对象的集合中
     *
     * @param conn     jdbc 连接
     * @param querySql 查询的 sql 语句
     * @param args     sql 中占位符的值
     * @param tClass   class
     * @param isUnderlineToCamel      是否要把表的列名的下划线转成驼峰
     * @param <T>      集合中要封装的数据的类型
     *
     * @return 查询到的所有数据
     */
    public static <T> List<T> queryList(Connection conn,
                                        String querySql,
                                        Object[] args,
                                        Class<T> tClass,
                                        boolean ... isUnderlineToCamel) {
        boolean defaultUnderlineToCamel = false; //  默认不转
        if (isUnderlineToCamel.length > 0) {
            defaultUnderlineToCamel = isUnderlineToCamel[0];
        }
        
        List<T> result = new ArrayList<>();
        // 1. 根据链接得到一个预处理语句
        try(PreparedStatement ps = conn.prepareStatement(querySql)) {
            // 2. 给 sql 中的占位符进行赋值
            for (int i = 0; args != null && i < args.length; i++) {
                Object arg = args[i];
                ps.setObject(i + 1, arg); // 占位符的索引是从 1 开始
            }
            // 3. 执行查询语句
            ResultSet resultSet = ps.executeQuery();
            ResultSetMetaData metaData = resultSet.getMetaData();
            // 4. 解析查询到的结果, 存储到 list 集合中
            // 4.1 遍历所有行, 每行封装到一个 T 类型的对象中, 存储到 List 集合中
            while (resultSet.next()) {
                // 4.2 创建该行的封装对象 T
                T t = tClass.newInstance();  // 通过反射利用无惨构造器创建对象
                // 4.3 遍历这行的每一列
                for (int i = 1; i <= metaData.getColumnCount(); i++) {
                    // 4.4 获取列名, 对应 T 对象中的属性名
                    String name = metaData.getColumnLabel(i);
                    if (defaultUnderlineToCamel) {
                        name = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name);   // a_a => aA aa_aa_aa =>aa_AaAa
                    }
                    // 4.5 获取对应的列的值
                    Object value = resultSet.getObject(i);
                    // 4.6 赋值到 T 对象中: t.name=value
                    BeanUtils.setProperty(t, name, value);
                    
                }
                BeanUtils.setProperty(t, "op", "r");
                result.add(t);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
        return result;
    }
    
    public static void closeConnection(Connection conn) throws SQLException {
        if (conn != null) {
            conn.close();
        }
    }
}
